package org.siteanalyser.util;

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.siteanalyser.service.SystemException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * General purpose XML utilities.
 * 
 * @author Luc Russell
 * 
 */
public class XmlUtils {

    /**
     * Look up the value at the given XPath in the supplied XML String. May
     * return null.
     * 
     * @param xml
     * @param xpathString
     * @return
     * @throws SystemException
     *             (RuntimeException)
     */
    public static String getXpathElementValue(final String xml, final String xpathString) throws SystemException {
        final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true); // never forget this!
        final StringReader reader = new StringReader(xml);
        final InputSource inputSource = new InputSource(reader);

        try {
            final DocumentBuilder builder = factory.newDocumentBuilder();
            final Document doc = builder.parse(inputSource);

            final XPathFactory xPathFactory = XPathFactory.newInstance();
            final XPath xpath = xPathFactory.newXPath();
            xpath.setNamespaceContext(new PersonalNamespaceContext());
            final XPathExpression expr = xpath.compile(xpathString);
            final Object result = expr.evaluate(doc, XPathConstants.NODESET);
            final NodeList nodes = (NodeList) result;
            if (nodes == null || nodes.item(0).equals(null)) {
                return null;
            }
            return nodes.item(0).getNodeValue();
        } catch (final ParserConfigurationException e) {
            throw new SystemException(e);
        } catch (final SAXException e) {
            throw new SystemException(e);
        } catch (final IOException e) {
            throw new SystemException(e);
        } catch (final XPathExpressionException e) {
            throw new SystemException(e);
        } finally {
            reader.close();
        }
    }

}
